// 扩展4.虚函数与纯虚函数的继承，子类中可被重写，final关键字使用
/**
 * #1 虚函数与纯虚函数的继承、final对虚函数使用
 * #2 关键字final对类使用
*/
#include <iostream>
#define __mark 1

/**
 * #1 虚函数与纯虚函数的继承、final对虚函数使用
*/
#if __mark == 1
class Test
{
protected:
public:
  void fun1()
  {
    std::cout << "基类Test 普通函数fun1" << std::endl;
  }

  virtual void fun2()
  {
    std::cout << "基类Test 虚函数fun2" << std::endl;
  }

  virtual void fun3() = 0; // 纯虚函数

  virtual void fun4() final
  {
    std::cout << "基类Test final 虚函数fun4" << std::endl;
  }

  // virtual void fun5() final = 0;
};

class _Test : public Test
{
public:
  void fun1()
  {
    std::cout << "类_Test 普通函数fun1" << std::endl;
  }

  void fun2()
  {
    std::cout << "重载基类Test 虚函数fun2" << std::endl;
  }

  void fun3()
  {
    std::cout << "重载基类Test 纯虚函数fun3" << std::endl;
  }

  // 不能重写final函数
  //  error: virtual function 'virtual void _Test::fun4()' overriding final function
  // void fun4(){
  //   std::cout << "重载基类Test final 虚函数fun4" << std::endl;
  // }

  // void fun5()
  // {
  //   std::cout << "重载基类Test final 纯虚函数fun5" << std::endl;
  // }
};

int main(void)
{
  _Test _t1; // error: cannot declare variable '_t1' to be of abstract type '_Test';估计final修饰的纯虚函数 还是被继承了，只是它不能被重载，_Test变成了抽象类；只要在_Test中不重写fun3就可以看出来
  // _t1.fun1();
  // _t1.fun2();

  Test *t;
  t = &_t1;
  t->fun1();
  t->fun2();
  t->fun3();

  printf("-----------------end-----------------\n");
  return 0;
}

/**
 * #2 关键字final对类使用
*/
#elif __mark == 2
class Test final
{
};

// error: cannot derive from 'final' base 'Test' in derived type '_Test'  不能将“final”类类型用作基类
class _Test : public Test
{
};

int main(void)
{
  printf("-----------------end-----------------\n");
  return 0;
}
#endif